From aba0c5cc3ba1f10492c9d9013802e287067b0bf7 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Sat, 3 Nov 2012 15:36:22 +0100 Subject: [PATCH] label: Redo get_preferred_width/height() This is important for size groups mostly, but also has some small fixes. The label-sizing reftest as been updated accordingly. --- gtk/gtklabel.c | 126 ++++++++++++----------------- tests/reftests/label-sizing.ref.ui | 8 +- 2 files changed, 56 insertions(+), 78 deletions(-) diff --git a/gtk/gtklabel.c b/gtk/gtklabel.c index 113ce5772f..e5b4849809 100644 --- a/gtk/gtklabel.c +++ b/gtk/gtklabel.c @@ -3439,23 +3439,6 @@ gtk_label_ensure_layout (GtkLabel *label) } } -static gint -get_single_line_height (GtkWidget *widget, - PangoLayout *layout) -{ - PangoContext *context; - PangoFontMetrics *metrics; - gint ascent, descent; - - context = pango_layout_get_context (layout); - metrics = get_font_metrics (context, widget); - ascent = pango_font_metrics_get_ascent (metrics); - descent = pango_font_metrics_get_descent (metrics); - pango_font_metrics_unref (metrics); - - return ascent + descent; -} - static GtkSizeRequestMode gtk_label_get_request_mode (GtkWidget *widget) { @@ -3512,11 +3495,12 @@ get_char_pixels (GtkWidget *label, static void gtk_label_get_preferred_layout_size (GtkLabel *label, - PangoRectangle *required, - PangoRectangle *natural) + PangoRectangle *widest, + PangoRectangle *highest) { GtkLabelPrivate *priv = label->priv; PangoLayout *layout; + gint char_pixels; /* "width-chars" Hard-coded minimum width: * - minimum size should be MAX (width-chars, strlen ("...")); @@ -3537,44 +3521,44 @@ gtk_label_get_preferred_layout_size (GtkLabel *label, /* Start off with the pixel extents of an as-wide-as-possible layout */ layout = gtk_label_get_measuring_layout (label, NULL, -1); - pango_layout_get_extents (layout, NULL, natural); - natural->x = natural->y = 0; - - if (priv->wrap) - natural->height = get_single_line_height (GTK_WIDGET (label), layout); + if (priv->width_chars > -1 || priv->max_width_chars > -1) + char_pixels = get_char_pixels (GTK_WIDGET (label), layout); + else + char_pixels = 0; + + pango_layout_get_extents (layout, NULL, widest); + widest->width = MAX (widest->width, char_pixels * priv->width_chars); + widest->x = widest->y = 0; if (priv->ellipsize || priv->wrap) { /* a layout with width 0 will be as small as humanly possible */ - layout = gtk_label_get_measuring_layout (label, layout, 0); - - pango_layout_get_extents (layout, NULL, required); + layout = gtk_label_get_measuring_layout (label, + layout, + priv->width_chars > -1 ? char_pixels * priv->width_chars + : 0); - /* can happen when Pango decides to ellipsize text */ - if (required->width > natural->width) - required->width = natural->width; + pango_layout_get_extents (layout, NULL, highest); + highest->width = MAX (highest->width, char_pixels * priv->width_chars); + highest->x = highest->y = 0; - required->x = required->y = 0; - required->height = natural->height; + if (priv->max_width_chars > -1 && widest->width > char_pixels * priv->max_width_chars) + { + layout = gtk_label_get_measuring_layout (label, + layout, + MAX (highest->width, char_pixels * priv->max_width_chars)); + pango_layout_get_extents (layout, NULL, widest); + widest->width = MAX (widest->width, char_pixels * priv->width_chars); + widest->x = widest->y = 0; + } + g_assert (widest->width >= highest->width); } else { - *required = *natural; + *highest = *widest; } - if (priv->width_chars > -1 || priv->max_width_chars > -1) - { - gint char_pixels; - - char_pixels = get_char_pixels (GTK_WIDGET (label), layout); - - if (priv->width_chars > -1) - required->width = MAX (required->width, char_pixels * priv->width_chars); - - if (priv->max_width_chars > -1) - natural->width = MIN (natural->width, priv->max_width_chars * char_pixels); - natural->width = MAX (natural->width, required->width); - } + g_assert (widest->height <= highest->height); g_object_unref (layout); } @@ -3587,36 +3571,28 @@ gtk_label_get_preferred_size (GtkWidget *widget, { GtkLabel *label = GTK_LABEL (widget); GtkLabelPrivate *priv = label->priv; - PangoRectangle required_rect; - PangoRectangle natural_rect; + PangoRectangle widest_rect; + PangoRectangle highest_rect; GtkBorder border; - gtk_label_get_preferred_layout_size (label, &required_rect, &natural_rect); + gtk_label_get_preferred_layout_size (label, &widest_rect, &highest_rect); /* Now that we have minimum and natural sizes in pango extents, apply a possible transform */ if (priv->have_transform) { - PangoLayout *copy; PangoContext *context; const PangoMatrix *matrix; - copy = pango_layout_copy (priv->layout); - context = pango_layout_get_context (copy); + context = pango_layout_get_context (priv->layout); matrix = pango_context_get_matrix (context); - pango_layout_set_width (copy, -1); - pango_layout_set_ellipsize (copy, PANGO_ELLIPSIZE_NONE); - - pango_layout_get_extents (copy, NULL, &natural_rect); - g_object_unref (copy); - - pango_matrix_transform_rectangle (matrix, &required_rect); - pango_matrix_transform_rectangle (matrix, &natural_rect); + pango_matrix_transform_rectangle (matrix, &widest_rect); + pango_matrix_transform_rectangle (matrix, &highest_rect); - /* Bump the natural size in case of ellipsize to ensure pango has + /* Bump the size in case of ellipsize to ensure pango has * enough space in the angles (note, we could alternatively set the * layout to not ellipsize when we know we have been allocated our - * full natural size, or it may be that pango needs a fix here). + * full size, or it may be that pango needs a fix here). */ if (priv->ellipsize && priv->angle != 0 && priv->angle != 90 && priv->angle != 180 && priv->angle != 270 && priv->angle != 360) @@ -3624,16 +3600,18 @@ gtk_label_get_preferred_size (GtkWidget *widget, /* For some reason we only need this at about 110 degrees, and only * when gaining in height */ - natural_rect.height += ROTATION_ELLIPSIZE_PADDING * 2 * PANGO_SCALE; - natural_rect.width += ROTATION_ELLIPSIZE_PADDING * 2 * PANGO_SCALE; + widest_rect.height += ROTATION_ELLIPSIZE_PADDING * 2 * PANGO_SCALE; + widest_rect.width += ROTATION_ELLIPSIZE_PADDING * 2 * PANGO_SCALE; + highest_rect.height += ROTATION_ELLIPSIZE_PADDING * 2 * PANGO_SCALE; + highest_rect.width += ROTATION_ELLIPSIZE_PADDING * 2 * PANGO_SCALE; } } - required_rect.width = PANGO_PIXELS_CEIL (required_rect.width); - required_rect.height = PANGO_PIXELS_CEIL (required_rect.height); + widest_rect.width = PANGO_PIXELS_CEIL (widest_rect.width); + widest_rect.height = PANGO_PIXELS_CEIL (widest_rect.height); - natural_rect.width = PANGO_PIXELS_CEIL (natural_rect.width); - natural_rect.height = PANGO_PIXELS_CEIL (natural_rect.height); + highest_rect.width = PANGO_PIXELS_CEIL (highest_rect.width); + highest_rect.height = PANGO_PIXELS_CEIL (highest_rect.height); _gtk_misc_get_padding_and_border (GTK_MISC (label), &border); @@ -3650,15 +3628,15 @@ gtk_label_get_preferred_size (GtkWidget *widget, */ get_size_for_allocation (label, GTK_ORIENTATION_VERTICAL, - required_rect.height, + highest_rect.height, minimum_size, natural_size); } else { /* Normal desired width */ - *minimum_size = required_rect.width; - *natural_size = natural_rect.width; + *minimum_size = highest_rect.width; + *natural_size = widest_rect.width; } *minimum_size += border.left + border.right; @@ -3677,7 +3655,7 @@ gtk_label_get_preferred_size (GtkWidget *widget, */ get_size_for_allocation (label, GTK_ORIENTATION_HORIZONTAL, - required_rect.width, + widest_rect.width, minimum_size, natural_size); } else @@ -3685,8 +3663,8 @@ gtk_label_get_preferred_size (GtkWidget *widget, /* A vertically rotated label does w4h, so return the base * desired height (text length) */ - *minimum_size = required_rect.height; - *natural_size = natural_rect.height; + *minimum_size = widest_rect.height; + *natural_size = highest_rect.height; } *minimum_size += border.top + border.bottom; diff --git a/tests/reftests/label-sizing.ref.ui b/tests/reftests/label-sizing.ref.ui index b33923dadb..eacaec4662 100644 --- a/tests/reftests/label-sizing.ref.ui +++ b/tests/reftests/label-sizing.ref.ui @@ -5457,7 +5457,7 @@ ABCD True False 0 - ABCDE + ABCDE ABCD 8 @@ -5476,7 +5476,7 @@ ABCD True False 0 - ABCDE + ABCDE ABCD 8 @@ -6099,7 +6099,7 @@ ABCD True False 0 - ABCDE + ABCDE ABCD 4 8 @@ -6119,7 +6119,7 @@ ABCD True False 0 - ABCDE + ABCDE ABCD 4 8 -- 2.30.2